package com.foreveross.chameleon.socket;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import com.foreveross.chameleon.base.PushApplication;
import com.foreveross.chameleon.nodeclient.MessageInfo;
import com.foreveross.chameleon.utils.*;
import com.foreveross.chameleon.zillasdk.Zilla;
import com.foreveross.chameleon.zillasdk.ZillaDelegate;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.msgpack.MessagePack;
import org.msgpack.type.Value;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * project:
 * author: wzq
 * date: 2014/7/22
 * description: 使用socket 发送、接收消息，并处理接收到的消息
 */
public class PushRTx {
    public final static String TAG = "PushRTx";
    private static final int HEARTBEAT_CYCLE = 5 * 60 * 1000;//定时任务时间间隔
    private static final int MAX_HEART_TRY_TIME = 3;//心跳最大尝试次数

    private static int countHeartSend = 0;
    private static int countHeartResp = 0;

    private static SocketConnect socket;
    private static MsgInterceptor msgInterceptor;   //消息拦截器

    /**
     * 消息拦截器接口
     */
    public interface MsgInterceptor {
        /**
         * 是否需要被拦截
         *
         * @param msg
         * @return
         */
        public boolean isNeedToIntercept(byte[] msg);

        /**
         * 处理被拦截的消息
         *
         * @param msg
         */
        public void handleMsg(byte[] msg);
    }

    /**
     * 注册消息拦截器
     *
     * @param interceptor
     */
    public static void registerMsgInterceptor(MsgInterceptor interceptor) {
        msgInterceptor = interceptor;
    }

    // 停止收发:关闭定时任务,清理
    public static void stopRTx() {
        if (socket != null) {
            //AppLog.i("stopRTx");
            countHeartSend = 0;
            countHeartResp = 0;
            heartSendTime.clear();
            stopTimerHeartBeat();
            socket = null;
        }
    }


    /** 开始收发:首先发送一个对象，收到回复后，发送心跳 */
    public static void startRTx(SocketConnect s, String token) {
        stopRTx();
        //
        socket = s;
        s.setSocketMsgHandler(msgHandler);
        sendEntity(token);
    }

    private static void sendEntity(String token) {
        AuthMessageEntity entity = new AuthMessageEntity();
        entity.setDeviceId(DeviceInfoUtil.getDeviceId());
        entity.setPushToken(token);
        String username = Preferences.getUserName();
        if (username == null || username.equals("")) {
            username = "guest";
        }
        entity.setUserName(username);
        try {
            byte[] msg = PackageUtil.ToByte(entity);
            //AppLog.i("socket 发送对象");
            socket.sendMsg(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** 收到消息，统一处理 入口 */
    private static SocketConnect.SocketMsgHandler msgHandler = new SocketConnect.SocketMsgHandler() {
        @Override
        public void onReceiveMsg(byte[] msg) {
            AppLog.i(TAG, "收到 socket 信息" + msg);

            // TODO:处理数据入口
            if (isHeartReply(GeneralUtils.copyBytes(msg))) {
                AppLog.d("PushPlugin", "是 心跳包");
                handleMsgHeartReply();
                return;
            }

            // 是否entity reply,
            Object entityReply = getEntityReply(GeneralUtils.copyBytes(msg));
            if (entityReply != null) {
                handleEntityReply((Boolean) entityReply);
                return;
            }

            /**
             * 消息拦截于此处理
             */
            if (msgInterceptor != null) {
                AppLog.d(TAG, "进入数据拦截...");
                if (msgInterceptor.isNeedToIntercept(msg)) {
                    msgInterceptor.handleMsg(msg);
                    return;
                }
            } else {
                AppLog.e("无拦截...");
            }
            // 常规 push信息
            AppLog.d("PushPlugin", "普通 push信息");
            //handleNormalMsg(msg);
        }
    };

    // 普通消息，先解析成JSON,再处理
//    private static void handleNormalMsg(byte[] bytes) {
//        try {
//            Value v = PackageUtil.byteToObject(bytes);
//            String msg = v.toString();
//            JSONObject jsonObj = new JSONObject(v.toString());
//            AppLog.d(TAG, "*****接收到的消息---->***" + msg);
//            final Context context = PushApplication.getApplication();
//            if (jsonObj.has("id")) { // 含有id,普通push信息
//                String id = jsonObj.getString("id");
//                if (null == id && "".equals(id)) {
//                    AppLog.e("PushPlugin", "push数据含有id字段，但是id为空");
//                } else {
//                    // 去拉取信息
//                    Zilla.getZilla().pushGetMessage(context, DeviceInfoUtil.getDeviceId(), PushConstants.APPKEY, new ZillaDelegate() {
//                        @Override
//                        public void requestStart() {
//
//                        }
//
//                        @Override
//                        public void requestSuccess(String result) {
//                            AppLog.d(TAG, "拉取推送的信息==>" + result);
//                            List<MessageInfo> msgList = parseMessage(result);
//                            StringBuffer sendIDs = new StringBuffer();
//                            for (MessageInfo msg : msgList) {
//                                String sendid = msg.getId();
//                                if (sendid != null && !sendid.equals("")) {
//                                    sendIDs.append(sendid + ",");
//                                }
//                            }
//                            if (sendIDs.length() != 0) {
//                                //向服务器发送接收信息的回执
//                                receiptsMessage(context, sendIDs.substring(0, sendIDs.length() - 1));
//                            }
//                            Intent it = new Intent();
//                            it.setAction(PushConstants.ACTION_REC_MESSAGE);
//                            it.putExtra("msg", result);
//                            context.sendBroadcast(it);
//                        }
//
//                        @Override
//                        public void requestFailed(String errorMessage) {
//                            AppLog.d(TAG, "拉取推送的消息失败==>");
//                        }
//                    });
//                }
//
//            } else {
//                AppLog.e("PushPlugin", "不识别(未处理)的push信息:" + jsonObj.toString());
//            }
//
//
//        } catch (JSONException e) {
//            AppLog.e("PushPlugin", "非心跳，push数据无法解析成json");// 格式错误
//        }
//    }

//    private static List<MessageInfo> parseMessage(String json) {
//        List<MessageInfo> msgList = null;
//        try {
//            JSONArray jsonArr = new JSONArray(json);
//            if (jsonArr.length() > 0) {
//                msgList = new ArrayList<MessageInfo>();
//            }
//            for (int i = 0; i < jsonArr.length(); i++) {
//                JSONObject jsonObj = jsonArr.getJSONObject(i);
//                MessageInfo msg = new MessageInfo();
//                if (jsonObj.has(MessageInfo.ID)) {
//                    msg.setId(jsonObj.getString(MessageInfo.ID));
//                }
//                if (jsonObj.has(MessageInfo.TITLE)) {
//                    msg.setTitle(jsonObj.getString(MessageInfo.TITLE));
//                }
//                if (jsonObj.has(MessageInfo.CONTENT)) {
//                    msg.setContent(jsonObj.getString(MessageInfo.CONTENT));
//                }
//                if (jsonObj.has(MessageInfo.MSG_TYPE)) {
//                    msg.setMessageType(jsonObj.getString(MessageInfo.MSG_TYPE));
//                }
//                if (jsonObj.has(MessageInfo.EXTRAS)) {
//                    msg.setExtras(jsonObj.getString(MessageInfo.EXTRAS));
//                }
//                if (jsonObj.has(MessageInfo.DIRC_EXTR_PRO)) {
//                    msg.setDerectExtrasPropertys(jsonObj.getString(MessageInfo.DIRC_EXTR_PRO));
//                }
//                AppLog.d(TAG, "parse msg count" + i);
//                msgList.add(msg);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return msgList;
//    }

//    /**
//     * 发送回执至服务器
//     *
//     * @param context
//     * @param msgId
//     */
//    private static void receiptsMessage(final Context context, String msgId) {
//        Zilla.getZilla().pushReceived(context, msgId, new ZillaDelegate() {
//
//            @Override
//            public void requestSuccess(String result) {
//                AppLog.d(TAG, "receiptsMessage Success");
//            }
//
//            @Override
//            public void requestStart() {
//            }
//
//            @Override
//            public void requestFailed(String errorMessage) {
//            }
//        });
//    }

    // 心跳得到回应
    private static void handleMsgHeartReply() {
        countHeartResp++;
        AppLog.i("PushPlugin", "发送心跳次数 =" + countHeartSend + ", 收到心跳回复 =" + countHeartResp);
        heartSendTime.clear();
    }

    /** 处理entity 回应 ， isTrue 响应的 result = isTrue */
    private static void handleEntityReply(boolean isTrue) {
        if (isTrue) { // 响应正确
            startTimerHeartBeat();
        } else {// 响应错误,表明上送数据不正确，清理token
            TokenGetter.clearCurrToken();
            stopRTx();
            PushSetup.getInstance().socketRTxErr();
        }
    }

    /**
     * 是否 entity的回应,如果是，则返回内容，不是则返回null
     */
    private static Object getEntityReply(byte[] bytes) {
        try {
            Value v = PackageUtil.byteToObject(bytes);
            JSONObject jsonObj = new JSONObject(v.toString());
            boolean r = jsonObj.getBoolean("result");
            return r;
        } catch (JSONException e) {
            // 不需要处理,这个数据不是 entity的回复
        }
        return null;
    }

    /** 定时器发送的 intent */
    private static PendingIntent timerIntent;

    private static PendingIntent getTimerIntent() {
        if (timerIntent == null) {
            //Context context = ChameleonApplication.getApplication();
            Context context = PushApplication.getApplication();
            Intent intent = new Intent(context, SendHeartbeatReceiver.class);
            intent.setAction("heartbeat.receiver");
            timerIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        }
        return timerIntent;
    }

    /** 启动定时任务:心跳 */
    private static void startTimerHeartBeat() {
        //AppLog.i("启动心跳:startTimerHeartBeat");
        //Context context = ChameleonApplication.getApplication();
        Context context = PushApplication.getApplication();
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(), HEARTBEAT_CYCLE, getTimerIntent());
    }

    /** 结束定时任务:心跳 */
    private static void stopTimerHeartBeat() {
        //AppLog.i("停止心跳:stopTimerHeartBeat");
        //Context context = ChameleonApplication.getApplication();
        Context context = PushApplication.getApplication();
        if (timerIntent != null) {
            AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            am.cancel(timerIntent);
            timerIntent = null;
        }
    }

    /** 单次心跳发送 */
    private static void heartOneTime() {
        if (heartSendTime.size() >= MAX_HEART_TRY_TIME) {// 已经有超过失败限额
            stopRTx();
            PushSetup.getInstance().socketRTxErr();
        } else {
            if (socket != null && socket.isAvailiable()) {
                // 增加一条心跳发送记录，该记录等待回应
                heartSendTime.add(SystemClock.currentThreadTimeMillis());
                byte[] heartSend = PackageUtil.ToByteNoJson("");
                socket.sendMsg(heartSend);
                countHeartSend++;
            } else {
                // socket已经无效了
                stopRTx();
                PushSetup.getInstance().socketRTxErr();
            }
        }
    }

    // 未响应的心跳记录，如果响应了，则清零
    private static ArrayList<Long> heartSendTime = new ArrayList<Long>();


    /** 定时器发送的 心跳广播,收到心跳广播后，发送心跳 */
    public static class SendHeartbeatReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //AppLog.d("SendHeartbeatReceiver::AlarmReceiver 收到广播 from Alarmer");
            heartOneTime();
        }
    }

    /** 判断是否为心跳回执 */
    private static boolean isHeartReply(byte[] btyes) {
        // 生成正确的心跳回应,
        byte[] right = {};
        try {
            byte b = new MessagePack().write("")[0];
            byte[] a = {0, 0, 0, 1, 1, b};
            right = a;
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 比较
        if (btyes.length != right.length) {
            return false;
        }
        for (int i = 0; i < btyes.length; i++) {
            if (btyes[i] != right[i]) {
                return false;
            }
        }
        return true;
    }

}
